Imports System.Reflection
Imports System
Imports System.Activator
Imports System.Type

''' -----------------------------------------------------------------------------
''' Project	 : BizBlox
''' Class	 : BizBlox.DOFactory
''' 
''' -----------------------------------------------------------------------------
''' <summary>
''' Create a data object using reflection
''' </summary>
''' <remarks>
''' </remarks>
''' <history>
''' 	[cinj]	16/06/2006	Created
''' </history>
''' -----------------------------------------------------------------------------
Public Class DOFactory
    Inherits System.MarshalByRefObject
    Private m_objType As Type

    Private Sub New()
    End Sub


    ''' -----------------------------------------------------------------------------
    ''' <summary>
    ''' Create a data object factory using the object as a prototype
    ''' </summary>
    ''' <param name="DOHnd"></param>
    ''' <remarks>
    ''' 
    ''' </remarks>
    ''' <history>
    ''' 	[cinj]	26/08/2004	Created
    ''' </history>
    ''' -----------------------------------------------------------------------------
    Public Sub New(ByVal DOHnd As DataObject)
        m_objType = DOHnd.GetType()
    End Sub


    ''' -----------------------------------------------------------------------------
    ''' <summary>
    ''' Create a data object factory using the type alone
    ''' </summary>
    ''' <param name="DOType"></param>
    ''' <remarks>
    ''' dim f as new DOFactory(GetType(MyDataObject))
    ''' </remarks>
    ''' <history>
    ''' 	[cinj]	26/08/2004	Created
    ''' </history>
    ''' -----------------------------------------------------------------------------
    Public Sub New(ByVal DOType As Type)
        m_objType = DOType
    End Sub

    ''' -----------------------------------------------------------------------------
    ''' <summary>
    ''' Return the type of Factory I am
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks>
    ''' </remarks>
    ''' <history>
    ''' 	[cinj]	26/08/2004	Created
    ''' </history>
    ''' -----------------------------------------------------------------------------
    Public Function getDOType() As Type
        Return m_objType
    End Function

    ''' -----------------------------------------------------------------------------
    ''' <summary>
    ''' create an empty data object
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks>
    ''' </remarks>
    ''' <history>
    ''' 	[cinj]	26/08/2004	Created
    ''' </history>
    ''' -----------------------------------------------------------------------------
    Public Overloads Function Create() As DataObject
        Return CType(Activator.CreateInstance(m_objType), DataObject)
    End Function

    ''' -----------------------------------------------------------------------------
    ''' <summary>
    ''' create an existing data object which maps to a table guid (existing)
    ''' </summary>
    ''' <param name="uid"></param>
    ''' <returns></returns>
    ''' <remarks>
    ''' Sets the GUID of the object but does not attempt to load it from the DB
    ''' If the GUID does not exist, an error will only be thrown when the read is 
    ''' attempted.
    ''' </remarks>
    ''' <history>
    ''' 	[cinj]	26/08/2004	Created
    ''' </history>
    ''' -----------------------------------------------------------------------------
    Public Overloads Function Create(ByVal uid As Guid) As DataObject
        Dim obj As DataObject = CType(Activator.CreateInstance(m_objType, New Object() {uid}), DataObject)
        Return obj
    End Function


    ''' -----------------------------------------------------------------------------
    ''' <summary>
    ''' Create an empty data object and populate it with the data from a Transfer Object
    ''' </summary>
    ''' <param name="transferObject"></param>
    ''' <returns></returns>
    ''' <remarks>
    ''' Transfer objects do not need to match all properties of DataObjects to populate them.
    ''' Whatever properties exist of the same type will be populated from the Transfer Object.
    ''' Property names of the Transfer Objects must match the DataObject - case sensitive!
    ''' This allows for cut-down Transfer Objects which exist for a specific task to update or 
    ''' populate a heavy weight DataObject.
    ''' </remarks>
    ''' <history>
    ''' 	[cinj]	26/08/2004	Created
    ''' </history>
    ''' -----------------------------------------------------------------------------
    Public Overloads Function Create(ByVal transferObject As DOTO) As DataObject
        Dim obj As DataObject = CType(Activator.CreateInstance(m_objType), DataObject)
        obj.AcceptTO(transferObject)
        Return obj
    End Function

    ''' -----------------------------------------------------------------------------
    ''' <summary>
    ''' Load a new DataObject using the primary key value
    ''' </summary>
    ''' <param name="uid">GUID primary key</param>
    ''' <returns></returns>
    ''' <remarks>
    ''' *If not a valid key the method will return Null (Nothing in Visual Basic)
    ''' </remarks>
    ''' <history>
    ''' 	[cinj]	26/08/2004	Created
    ''' </history>
    ''' -----------------------------------------------------------------------------
    Public Overloads Function Retrieve(ByVal uid As Guid) As DataObject
        Dim obj As DataObject = Create(uid)
        Try
            obj.Load()
        Catch ex As Exception
            Return Nothing
        End Try
        Return obj
    End Function

    ''' -----------------------------------------------------------------------------
    ''' <summary>
    ''' Load a new DataObject using the primary key value from a TransferObject
    ''' </summary>
    ''' <param name="transferObject">Transfer Object with a mapped primary key property (of the same data type)</param>
    ''' <returns></returns>
    ''' <remarks>
    ''' *The TransferObject MUST have a property with the name of the DataObject primary key or the method will return Null (Nothing in Visual Basic)
    ''' </remarks>
    ''' <history>
    ''' 	[cinj]	26/08/2004	Created
    ''' </history>
    ''' -----------------------------------------------------------------------------
    Public Overloads Function Retrieve(ByVal transferObject As DOTO) As DataObject
        Dim uid As Guid
        Dim tmpObj As DataObject = CType(Activator.CreateInstance(m_objType), DataObject)
        Dim pInfo As PropertyInfo = transferObject.GetType().GetProperty(tmpObj.UIDColumnName(), GetType(Guid))
        If Not pInfo Is Nothing Then
            uid = transferObject.GetType().InvokeMember(pInfo.Name, BindingFlags.NonPublic Or BindingFlags.GetProperty Or BindingFlags.Public Or BindingFlags.Instance, Nothing, transferObject, New Object() {})
            Return Retrieve(uid)
        Else
            Return Nothing
        End If
    End Function

    ''' -----------------------------------------------------------------------------
    ''' <summary>
    ''' Uses the matching primary key column of the TransferObject and this DataObject to perform a Retrieve() 
    ''' then it will perform an Accept() to copy all properties which are set on the TransferObject over to the 
    ''' freshly loaded DataObject. 
    ''' </summary>
    ''' <param name="transferObject"></param>
    ''' <returns></returns>
    ''' <remarks>
    ''' *Properties which are not mapped from the TransferObject to the DataObject will retain the data which existed in them when loaded.
    ''' *Properties which exist in the TransferObject and not the DataObject will not be copied to the DataObject
    ''' *The TransferObject MUST have a property with the name of the DataObject primary key or the method will return Null (Nothing in Visual Basic)
    ''' </remarks>
    ''' <history>
    ''' 	[cinj]	26/08/2004	Created
    ''' </history>
    ''' -----------------------------------------------------------------------------
    Public Function Update(ByVal transferObject As DOTO) As DataObject
        Dim obj As DataObject = Retrieve(transferObject)
        If Not obj Is Nothing Then
            obj.AcceptTO(transferObject)
        End If
        Return obj
    End Function

End Class
